
#include "DailySchedule.h"
#include "Util/logc.h"
#include "Protocol/ProtocolApi.h"
#include <regex>
#include <iostream>

namespace Media{

    std::string months[] = {
        "January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December"
    };

    std::string weekdays[] = {
        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
    };

    DailySchedule::Ptr DailySchedule::Instance(){
        static auto ptr = std::make_shared<DailySchedule>();
        return ptr;
    }

    DailySchedule::DailySchedule(){
        createFont("/user/data/osd/siyuan.ttf", 32, FT_FONT_STYLE_NORMAL, m_font32Normal);
        createFont("/user/data/osd/siyuan.ttf", 32, FT_FONT_STYLE_BOLD, m_font32Bold);

        createFont("/user/data/osd/siyuan.ttf", 16, FT_FONT_STYLE_NORMAL, m_font16Normal);
        createFont("/user/data/osd/siyuan.ttf", 20, FT_FONT_STYLE_NORMAL, m_font20Normal);
        createFont("/user/data/osd/siyuan.ttf", 20, FT_FONT_STYLE_BOLD, m_font20Bold);
        createFont("/user/data/osd/siyuan.ttf", 12, FT_FONT_STYLE_NORMAL, m_font12Normal);
        
    }

    void DailySchedule::clearResources() {
        // 删除根对象，会递归删除其子对象
        // 样式对象重置
        lv_style_reset(&m_dailyTransactionPage_style);
        lv_style_reset(&m_dailyTransactionTop_style);
        lv_style_reset(&m_dailyTransactionTopLabelStyle);
        lv_style_reset(&m_dailyTransactionTopLabelStyleDayStyle);
        lv_style_reset(&m_dailyTransactionMiddle_style);
        lv_style_reset(&m_LabelDayGmtStyle);
        lv_style_reset(&m_LabelDayDayStyle);
        lv_style_reset(&m_dailyTransactionBottomSupper_style);
        lv_style_reset(&m_dailyTransactionMiddleLeftSupper_style);
        lv_style_reset(&m_dailyTransactionMiddleMiddleSupper_style);
        lv_style_reset(&m_dailyTransactionBottomRightSupper_style);
        lv_style_reset(&m_TimeHourFrameStyle);
        lv_style_reset(&m_TimeHourItemStyle);
        lv_style_reset(&m_DotlineFrameStyle);
        lv_style_reset(&m_DotlineItemStyle);
        lv_style_reset(&m_scheduleSummaryStyle);
        lv_style_reset(&m_scheduleTimeStyle);
        if (m_dailyTransactionPage != nullptr) {
            lv_obj_del(m_dailyTransactionPage);
            m_dailyTransactionPage = nullptr;
        }

        for(int i = 0;i < m_scheduleItemStyles.size(); i++){
            lv_style_reset(&m_scheduleItemStyles[i]);
        }
        m_scheduleItemStyles.clear();

        for(int i = 0; i < m_scheduleItem.size(); i++){
            lv_obj_del(m_scheduleItem[i]);
        }
        m_scheduleItem.clear();
        m_scheduleIndex = -1;
       
    }

    bool DailySchedule::getDailyScheduleDate(){
        //获取熏染的数据
        std::string response;
        Json::Value table;
        Json::Reader reader;
        //请求日历数据
        Protocol::IProtocolInterface::GetInstance()->AuditoryworksSendRequest("DailySchedule", "", response, 5);
        if(response.empty()){
            errorf("AuditoryworksSendRequest NotiftyCloudUpdateStream faild\n");
            return false;
        }
        //tracef("response ----> %s\n", response.c_str());
        if(!reader.parse(response, table) || !table.isMember("data")){
            errorf("response data parse faild\n");
            return false;
        }
      
        m_dailyTable = table["data"];

        if(!m_dailyTable.isMember("items") || !m_dailyTable["items"].isArray()){
            errorf("response data parse faild\n");
        }
        if(!table.isMember("time") || !table["time"].isString()){
            errorf("response data parse faild\n");
        }
        parseISO8601ToTimeT(table["time"].asString() , m_curTime);
        m_curtm = std::gmtime(&m_curTime);
        m_timeZone =  "GMT " + table["time"].asString().substr(table["time"].asString().length() - 6);
        warnf("m_curTime -----------------------> %ld\n", m_curTime);
        filterShowSchedule(m_dailyTable["items"]);


        

        
        return true;
    }


    
    bool DailySchedule::sortSchedule(Json::Value &table){
        if(!table.isArray()){
            errorf("params error\n");
        }
        // 使用冒泡排序对 JSON 数组进行排序
        for (Json::Value::ArrayIndex i = 0; i < table.size(); ++i) {
            for (Json::Value::ArrayIndex j = i + 1; j < table.size(); ++j) {
                bool shouldSwap = false;
                if (table[i]["start"].asInt64() > table[j]["start"].asInt64()) {
                    shouldSwap = true;
                } else if (table[i]["start"].asInt64() == table[j]["start"].asInt64()) {
                    if (table[i]["end"].asInt64() < table[j]["end"].asInt64()) {
                        shouldSwap = true;
                    }
                }

                if (shouldSwap) {
                    std::swap(table[i], table[j]);
                }
            }
        }
    
        return true;
    }

    
    bool DailySchedule::groupSchedule(const Json::Value table, Json::Value& groupTable){
        //判断参数
        if(!table.isArray() || !groupTable.isArray()){
            errorf("groupSchedule params error\n");
            return false;
        }
        std::vector<int> crossArray;
        //遍历每一条日程，将其放入分组
        for(int i = 0; i < table.size(); i++){
            crossArray.clear();
            //对于每一条日程，判断与分组的交叠关系，记录所有有交叠关系
            for(int j = 0; j < groupTable.size(); j++){
                //判断交叠关系,交叠则加入列表
                if(!(table[i]["end"].asInt64() <= groupTable[j]["GroupStart"].asInt64() || table[i]["start"].asInt64() >= groupTable[j]["GroupEnd"].asInt64())){
                    crossArray.push_back(j);
                }
            }            

            Json::Value groupItem;
            if(crossArray.size() == 0){
                //如果没有交叠的分组直接创建一个分组
                groupItem["GroupStart"] = static_cast<Json::Int64>(table[i]["start"].asInt64());
                groupItem["GroupEnd"] = static_cast<Json::Int64>(table[i]["end"].asInt64());
                groupItem["schedules"].append(table[i]);
            }else{
                groupItem["GroupStart"] = static_cast<Json::Int64>(table[i]["start"].asInt64());
                groupItem["GroupEnd"] = static_cast<Json::Int64>(table[i]["end"].asInt64());
                groupItem["schedules"].append(table[i]);
                //有交叠则分组合并
                //分组合并其实就是将几个json数组合并成一个并且记录最大值和最小值
                for(int m = 0; m < crossArray.size(); m++){
                    for(int n = 0; n < groupTable[crossArray[m]]["schedules"].size(); n++){
                        if(groupItem["GroupStart"].asInt64() > groupTable[crossArray[m]]["schedules"][n]["start"].asInt64()){
                            groupItem["GroupStart"] = groupTable[crossArray[m]]["schedules"][n]["start"].asUInt64();
                        }
                        if(groupItem["GroupEnd"].asInt64() < groupTable[crossArray[m]]["schedules"][n]["end"].asInt64()){
                            groupItem["GroupEnd"] = groupTable[crossArray[m]]["schedules"][n]["end"].asInt64();
                        }
                        
                        groupItem["schedules"].append(groupTable[crossArray[m]]["schedules"][n]);
                    }
                }
                for(int k = crossArray.size() - 1; k >= 0 ; k--){
                    Json::Value tmp;
                    groupTable.removeIndex(crossArray[k], &tmp);
                }
            }
            sortSchedule(groupItem["schedules"]);
            groupTable.append(groupItem);
        }
        return true;
    }


    bool DailySchedule::unoverlapGroup(Json::Value& groupScheduleTable, Json::Value& unoverlapTable){
        //判断参数
        if(!groupScheduleTable.isMember("schedules") || !groupScheduleTable["schedules"].isArray()){
            errorf("unoverlapGroup params error\n");
            return false;
        }
        if(!unoverlapTable.isArray()){
            errorf("unoverlapGroup params error\n");
            return false;
        }
        //创建数组用于保存最终需要删除的日程
        std::vector<int> removeData;
        //先将第一个数据加入到分离组中
        unoverlapTable.append(groupScheduleTable["schedules"][0]);
        removeData.push_back(0);
        long unoverlapStart = groupScheduleTable["schedules"][0]["start"].asInt64();
        long unoverlapEnd = groupScheduleTable["schedules"][0]["end"].asInt64();
        //遍历日程组数据
        for (int i = 1; i < groupScheduleTable["schedules"].size(); i++)
        {
            //判断当前的日程是否与分离出来的数据组存在交叠
            if(groupScheduleTable["schedules"][i]["start"].asInt64() >= unoverlapEnd || groupScheduleTable["schedules"][i]["end"].asInt64() <= unoverlapStart){
                //不存在交叠直接加入到分离组中
                unoverlapTable.append(groupScheduleTable["schedules"][i]);
                removeData.push_back(i);
                //记录最早开始时间和最晚结束时间方便后续交叠判断
                if(groupScheduleTable["schedules"][i]["start"].asInt64() < unoverlapStart){
                    unoverlapStart = groupScheduleTable["schedules"][i]["start"].asInt64();
                }

                if(groupScheduleTable["schedules"][i]["end"].asInt64() > unoverlapEnd){
                    unoverlapEnd = groupScheduleTable["schedules"][i]["end"].asInt64();
                }
            }
        }
        //记录删除
        for (int i = removeData.size() - 1; i >= 0; i--)
        {
            Json::Value tmp;
            groupScheduleTable["schedules"].removeIndex(removeData[i], &tmp);
            tracef("tmp -------------> %s\n", tmp.toStyledString().c_str());
        }
        
        return true;
    }

    //这个函数需要反复调用直到所有的日程全部删除完毕
    bool DailySchedule::ScheduleToShowTable(Json::Value &groupTable, Json::Value& showTable){
        //判断参数
        if(!groupTable.isArray() || !showTable.isArray()){
            errorf("ScheduleToShowTable params error\n");
            return false;
        }
        //创建图层
        Json::Value coverAgeItem;
        Json::Value unoverLapItem{Json::arrayValue};
        std::vector<int> emptyGreup;
        //遍历分组列表
        for (int i = 0; i < groupTable.size(); i++)
        {   
            unoverLapItem.clear();
            //分裂出分组列表中的不交叠部分，封装一个函数专门干这个事
            unoverlapGroup(groupTable[i], unoverLapItem);
            //判断分离之后是否还有数据，记录一下无数据需要在遍历完毕之后删除这一项
            if(groupTable[i]["schedules"].size() == 0){
                emptyGreup.push_back(i);
            }
            //添加到图层中
            for (int j = 0; j < unoverLapItem.size(); j++)
            {
                coverAgeItem.append(unoverLapItem[j]);
            }
        }
        showTable.append(coverAgeItem);
        //删除空数据    
        for (int i = emptyGreup.size() - 1; i >= 0; i--)
        {
            Json::Value tmp;
            groupTable.removeIndex(emptyGreup[i], &tmp);
        }
        
        return true;
    }


    bool DailySchedule::caculCoordinate(const Json::Value &showTable, Json::Value &coordinateTable, unsigned int width, unsigned int height,  unsigned int stepLenth){
        //判断参数
        if(!showTable.isArray() || !coordinateTable.isArray()){
            errorf("caculCoordinate params error\n");
            return false;
        }

        long startShowTime = m_curTime - 3600 * 2;
        long endShowTime = m_curTime + 3600 * 2;
        Json::Value coordinateItem{Json::arrayValue};
        Json::Value item;

        for (int i = 0; i < showTable.size(); i++)
        {
            coordinateItem.clear();
            for(int j = 0; j < showTable[i].size(); j++){
                item.clear();
                item["y"] = (showTable[i][j]["start"].asInt64() -  startShowTime) *  height / (endShowTime - startShowTime);
                item["yLen"] = (showTable[i][j]["end"].asInt64() - showTable[i][j]["start"].asInt64()) * height / (endShowTime - startShowTime);
                item["x"] = i * stepLenth;
                int lenght = width - (i * stepLenth);
                item["xLen"] = lenght >= 0 ? lenght : 0;
                item["summary"] = showTable[i][j]["summary"].asString();
                item["start"] = showTable[i][j]["start"].asInt64();
                item["end"] = showTable[i][j]["end"].asInt64();
                coordinateItem.append(item);
            }
            coordinateTable.append(coordinateItem);
        }
        
        return true;
    }

    bool DailySchedule::filterShowSchedule(Json::Value items){
        //这里过滤出来四个小时的数据
        Json::Value scheduleItem;
        time_t time;
        m_items.clear();
        //定义需要显示数据的边界
        long startShowTime = m_curTime - 3600 * 2;
        long endShowTime = m_curTime + 3600 * 2;
        for(int i = items.size() - 1;i >= 0; i--){
            if(items[i].isMember("summary") && items[i]["summary"].isString()){
                scheduleItem["summary"] = items[i]["summary"].asString();
            }else{
                scheduleItem["summary"] = "DefaultTitle";
            }
            parseISO8601ToTimeT(items[i]["start"]["dateTime"].asString() , time);
            scheduleItem["start"] =  static_cast<Json::Int64>(time);
            parseISO8601ToTimeT(items[i]["end"]["dateTime"].asString() , time);
            scheduleItem["end"] =  static_cast<Json::Int64>(time);
            
            //筛选出需要展示的数据,并且进行日程切割处理
            if(!(scheduleItem["end"].asInt64() <= startShowTime || scheduleItem["start"].asInt64() >= endShowTime)){
                if(scheduleItem["end"].asInt64() > endShowTime){
                    scheduleItem["end"] = static_cast<Json::Int64>(endShowTime);
                }
                if(scheduleItem["start"].asInt64() < startShowTime){
                    scheduleItem["start"] = static_cast<Json::Int64>(startShowTime);
                }
                m_items.append(scheduleItem);
            }
        }
        //排序，排序的规则是按照开始时间排序，时间一样的按照日程时长从长到短排序
        if(!sortSchedule(m_items)){
            errorf("sortSchedule faild!\n");
            return false;
        }
        
        //日程分组
        warnf("m_items-------------> %s\n", m_items.toStyledString().c_str());
        m_group.clear();
        if(!groupSchedule(m_items, m_group)){
            errorf("groupSchedule faild\n");
            return false;
        }
        warnf("m_group-------------> %s\n", m_group.toStyledString().c_str());
        //组数据转换为图层
        m_showTable.clear();
        while(m_group.size() != 0){
            if(!ScheduleToShowTable(m_group, m_showTable)){
                errorf("ScheduleToShowTable faild\n");
                return false;
            }
        }
        warnf("m_showTable-------------> %s\n", m_showTable.toStyledString().c_str());
        //图层数据换算成坐标
        m_coordinateTable.clear();
        caculCoordinate(m_showTable, m_coordinateTable, 1731, 816,  173);
        warnf("m_coordinateTable-------------> %s\n", m_coordinateTable.toStyledString().c_str());
        return true;
    }


   
    bool DailySchedule::parseISO8601ToTimeT(const std::string& iso8601, std::time_t& timeT) {
        std::tm tm = {};
        char sign;
        int hours = 0, minutes = 0;
        
        // 解析日期和时间部分，忽略毫秒部分
        std::istringstream datetimeStream(iso8601.substr(0, 19));
        datetimeStream >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");

        if (datetimeStream.fail()) {
            return false;
        }

        // 将tm转换为time_t
        timeT = std::mktime(&tm);
        if (timeT == -1) {
            return false;
        }

#if 0
        // 查找时区部分的位置
        size_t timezone_pos = iso8601.find_last_of("+-");
        if (timezone_pos == std::string::npos) {
            // 如果没有提供时区信息，则默认为+00:00
            sign = '+';
            hours = minutes = 0;
        } else {
            sign = iso8601[timezone_pos];
            std::string timezonePart = iso8601.substr(timezone_pos);
            
            warnf("timezonePart: %s    iso8601 --------------------------------end1\n", timezonePart.c_str());
            // 使用正则表达式来解析时区部分
            std::regex timezoneRegex(R"([+-](\d{2}):(\d{2}))");
            std::smatch matches;
            if (std::regex_match(timezonePart, matches, timezoneRegex)) {
                hours = std::stoi(matches[1].str());
                minutes = std::stoi(matches[2].str());
            } else {
                return false; // 时区格式不正确
            }
        }

        // 计算时区偏移量并调整time_t
        long offset = (hours * 3600 + minutes * 60) * (sign == '+' ? -1 : 1);
        warnf("hours:%d    minutes:%d offset:%ld  timeT:%ld\n", hours, minutes, offset, timeT);
        timeT += offset;
#endif
        
        return true;
    }

    void DailySchedule::DailyTransactionPage(){
        std::lock_guard<std::mutex> lock(m_showLock); 
        
        //回去需要渲染的数据
        if(!getDailyScheduleDate()){
            return ;
        }

        //释放资源避免内存泄漏
        clearResources();  

        
        //创建一个弹性布局先画出上中下三段的基本页面
        m_dailyTransactionPage = lv_obj_create(lv_scr_act());
        lv_obj_set_size(m_dailyTransactionPage, 1920, 1080);
        lv_obj_set_flex_flow(m_dailyTransactionPage, LV_FLEX_FLOW_COLUMN);
        lv_obj_set_flex_align(m_dailyTransactionPage,LV_FLEX_ALIGN_START ,LV_FLEX_ALIGN_START ,LV_FLEX_ALIGN_START );
        lv_obj_set_style_pad_all(m_dailyTransactionPage, 0 ,0);
        lv_obj_set_style_pad_gap(m_dailyTransactionPage, 0, 0);
        // 禁用水平和垂直滚动条
        lv_obj_clear_flag(m_dailyTransactionPage, LV_OBJ_FLAG_SCROLLABLE);
      
        //日历显示的上部分
        m_dailyTransactionTop  = lv_obj_create(m_dailyTransactionPage);
        lv_obj_set_size(m_dailyTransactionTop , 1920, 124);
        lv_style_set_border_width(&m_dailyTransactionTop_style, 0);
        lv_style_set_radius(&m_dailyTransactionTop_style, 0);
        lv_obj_set_style_pad_all(m_dailyTransactionTop, 0 ,0);
        lv_obj_set_style_pad_gap(m_dailyTransactionTop, 0, 0);
        lv_obj_add_style(m_dailyTransactionTop, &m_dailyTransactionTop_style, LV_PART_MAIN);
#if 1
        //文字显示当前时间
        m_dailyTransactionTopLabel = lv_label_create(m_dailyTransactionTop);
        lv_obj_set_size(m_dailyTransactionTopLabel, 500, 36);
        
        std::string dateDecr = months[m_curtm->tm_mon] + "   " + std::to_string(m_curtm->tm_mon + 1) + "," + std::to_string(m_curtm->tm_year + 1900) + "   " + weekdays[m_curtm->tm_wday];
        lv_label_set_text_fmt(m_dailyTransactionTopLabel, dateDecr.c_str());
        lv_style_set_text_font(&m_dailyTransactionTopLabelStyle, m_font32Normal.font);
        lv_style_set_text_color(&m_dailyTransactionTopLabelStyle, lv_color_black());
        lv_obj_add_style(m_dailyTransactionTopLabel, &m_dailyTransactionTopLabelStyle, LV_PART_MAIN);
        lv_obj_align(m_dailyTransactionTopLabel, LV_ALIGN_TOP_LEFT, 40, 44);

        m_dailyTransactionTopLabel = lv_label_create(m_dailyTransactionTop);
        lv_obj_set_size(m_dailyTransactionTopLabel, 114, 36);
        
        lv_style_set_border_color(&m_dailyTransactionTopLabelStyleDayStyle, lv_color_make(0x70, 0x39, 0xff));
        lv_style_set_border_width(&m_dailyTransactionTopLabelStyleDayStyle, 1);
        lv_label_set_text_fmt(m_dailyTransactionTopLabel, "Day");
        lv_style_set_radius(&m_dailyTransactionTopLabelStyleDayStyle, 8);
        lv_style_set_pad_top(&m_dailyTransactionTopLabelStyleDayStyle, 6);
        lv_style_set_text_align(&m_dailyTransactionTopLabelStyleDayStyle, LV_TEXT_ALIGN_CENTER);
        lv_style_set_text_font(&m_dailyTransactionTopLabelStyleDayStyle, m_font16Normal.font);
        lv_style_set_text_color(&m_dailyTransactionTopLabelStyleDayStyle, lv_color_make(0x70, 0x39, 0xff));
        lv_obj_add_style(m_dailyTransactionTopLabel, &m_dailyTransactionTopLabelStyleDayStyle, LV_PART_MAIN);
        lv_obj_align(m_dailyTransactionTopLabel, LV_ALIGN_TOP_RIGHT, -36, 40);

        
        
        
    
        //日历显示的中部分
        m_dailyTransactionMiddle  = lv_obj_create(m_dailyTransactionPage);
        lv_obj_set_size(m_dailyTransactionMiddle , 1920, 85);
        lv_obj_set_style_pad_all(m_dailyTransactionMiddle, 0 ,0);
        lv_obj_set_style_pad_gap(m_dailyTransactionMiddle, 0, 0);
        lv_obj_set_style_bg_opa(m_dailyTransactionMiddle, 25, 0);
        
        lv_style_set_bg_color(&m_dailyTransactionMiddle_style, lv_palette_main(LV_PALETTE_PINK));
        lv_style_set_border_color(&m_dailyTransactionMiddle_style, lv_color_make(0x70, 0x39, 0xff));
        lv_style_set_border_width(&m_dailyTransactionMiddle_style, 0);
        lv_style_set_radius(&m_dailyTransactionMiddle_style, 0);
        lv_obj_add_style(m_dailyTransactionMiddle, &m_dailyTransactionMiddle_style, LV_PART_MAIN);
       

        m_dailyTransactionMiddleLabel = lv_label_create(m_dailyTransactionMiddle);
        lv_obj_set_size(m_dailyTransactionMiddleLabel, 155, 54);
        lv_obj_align(m_dailyTransactionMiddleLabel, LV_ALIGN_TOP_LEFT, 54, 31);
        lv_label_set_text_fmt(m_dailyTransactionMiddleLabel, m_timeZone.c_str());

        lv_style_set_text_align(&m_LabelDayGmtStyle, LV_TEXT_ALIGN_CENTER);
        lv_style_set_text_font(&m_LabelDayGmtStyle, m_font20Normal.font);
        lv_style_set_text_opa(&m_LabelDayGmtStyle, 210);
        lv_obj_add_style(m_dailyTransactionMiddleLabel, &m_LabelDayGmtStyle, LV_PART_MAIN);
        
        
        m_dailyTransactionMiddleLabel = lv_label_create(m_dailyTransactionMiddle);
        lv_obj_set_size(m_dailyTransactionMiddleLabel, 200, 36);
        lv_obj_align(m_dailyTransactionMiddleLabel, LV_ALIGN_TOP_LEFT, 903, 24);
        std::string dateDecr1 = months[m_curtm->tm_mon] + " " + std::to_string(m_curtm->tm_mon + 1);
        lv_label_set_text_fmt(m_dailyTransactionMiddleLabel, dateDecr1.c_str());
        lv_style_set_text_align(&m_LabelDayDayStyle, LV_TEXT_ALIGN_CENTER);
        lv_style_set_text_font(&m_LabelDayDayStyle, m_font32Bold.font);
        lv_style_set_text_color(&m_LabelDayDayStyle, lv_color_make(0x70, 0x39, 0xff));
        lv_obj_add_style(m_dailyTransactionMiddleLabel, &m_LabelDayDayStyle, LV_PART_MAIN);
       
        
    
    
        m_dailyTransactionBottomSupper =  lv_obj_create(m_dailyTransactionPage);
        lv_obj_set_size(m_dailyTransactionBottomSupper, 1920, 871);
        lv_obj_set_style_pad_all(m_dailyTransactionBottomSupper, 0 ,0);
        lv_obj_set_style_pad_gap(m_dailyTransactionBottomSupper, 0, 0);
        //布局
        lv_obj_set_flex_flow(m_dailyTransactionBottomSupper, LV_FLEX_FLOW_ROW);
        lv_obj_set_flex_align(m_dailyTransactionBottomSupper,LV_FLEX_ALIGN_START ,LV_FLEX_ALIGN_START ,LV_FLEX_ALIGN_START );
        
        lv_style_set_border_width(&m_dailyTransactionBottomSupper_style, 0);
        lv_style_set_radius(&m_dailyTransactionBottomSupper_style, 0);
        //lv_style_set_bg_color(&m_dailyTransactionBottomSupper_style, lv_palette_main(LV_PALETTE_PINK));
        lv_obj_add_style(m_dailyTransactionBottomSupper, &m_dailyTransactionBottomSupper_style, LV_PART_MAIN);
  
       
  
        m_dailyTransactionBottomLeftSupper = lv_obj_create(m_dailyTransactionBottomSupper);
        lv_obj_set_size(m_dailyTransactionBottomLeftSupper , 144, 871);
        lv_obj_set_style_pad_all(m_dailyTransactionBottomLeftSupper, 0 ,0);
        lv_style_set_border_width(&m_dailyTransactionMiddleLeftSupper_style, 0);
        lv_style_set_radius(&m_dailyTransactionMiddleLeftSupper_style, 0);
        //lv_style_set_bg_color(&m_dailyTransactionMiddleLeftSupper_style, lv_palette_main(LV_PALETTE_YELLOW));
        lv_obj_add_style(m_dailyTransactionBottomLeftSupper, &m_dailyTransactionMiddleLeftSupper_style, LV_PART_MAIN);

        m_dailyTransactionMiddleLeftSupper = lv_obj_create(m_dailyTransactionBottomSupper);
        lv_obj_set_size(m_dailyTransactionMiddleLeftSupper , 39, 871);
        lv_obj_set_style_pad_all(m_dailyTransactionMiddleLeftSupper, 0 ,0);
        lv_style_set_border_width(&m_dailyTransactionMiddleMiddleSupper_style, 1);
        lv_style_set_border_side(&m_dailyTransactionMiddleMiddleSupper_style, LV_BORDER_SIDE_RIGHT);
        lv_style_set_border_color(&m_dailyTransactionMiddleMiddleSupper_style, lv_palette_main(LV_PALETTE_GREY));
        lv_style_set_radius(&m_dailyTransactionMiddleMiddleSupper_style, 0);
        //lv_style_set_bg_color(&m_dailyTransactionMiddleMiddleSupper_style, lv_palette_main(LV_PALETTE_YELLOW));
        lv_obj_add_style(m_dailyTransactionMiddleLeftSupper, &m_dailyTransactionMiddleMiddleSupper_style, LV_PART_MAIN);

        m_dailyTransactionBottomRightSupper = lv_obj_create(m_dailyTransactionBottomSupper);
        lv_obj_set_size(m_dailyTransactionBottomRightSupper , 1737, 871);
        lv_obj_set_style_pad_all(m_dailyTransactionBottomRightSupper, 0 ,0);
        lv_style_set_border_width(&m_dailyTransactionBottomRightSupper_style, 0);
        lv_style_set_radius(&m_dailyTransactionBottomRightSupper_style, 0);
        //lv_style_set_bg_color(&m_dailyTransactionBottomRightSupper_style, lv_palette_main(LV_PALETTE_LIGHT_GREEN));
        lv_obj_add_style(m_dailyTransactionBottomRightSupper, &m_dailyTransactionBottomRightSupper_style, LV_PART_MAIN);
        
        //判断参数
        int excurtion = m_curtm ->tm_min;
        //根据参数确定线的条数，除了整点时刻是5条其他时候都是4条
        if(excurtion != 0){
            m_dotlineNum = 4;
            m_padding = (60 - excurtion) * 3.4;
        }else{
            m_dotlineNum = 5;
            m_padding = 0;   
        }

       
        TimeHour();
        Dottedline();

        showScheduleData(m_coordinateTable);
        #endif
    }

    void DailySchedule::showScheduleData(const Json::Value &coordinateTable){
        lv_style_set_text_align(&m_scheduleSummaryStyle, LV_TEXT_ALIGN_CENTER);
        lv_style_set_text_font(&m_scheduleSummaryStyle, m_font20Bold.font);
        
        lv_style_set_text_align(&m_scheduleTimeStyle, LV_TEXT_ALIGN_CENTER);
        lv_style_set_text_font(&m_scheduleTimeStyle, m_font12Normal.font);
        lv_style_set_text_opa(&m_scheduleTimeStyle, 102);

        m_scheduleItemStyles.resize(m_items.size());
        //遍历所所有需要显示的日程，每条日程一个窗体
        for (int i = 0; i < coordinateTable.size(); i++)
        {   
            for(int j = 0; j < coordinateTable[i].size(); j++){
                m_scheduleIndex++;
                //创建窗体，设置窗体的基本属性以及基本样式
                m_scheduleItem.push_back(lv_obj_create(lv_scr_act()));
                lv_obj_set_size(m_scheduleItem[m_scheduleIndex] , (int16_t)(coordinateTable[i][j]["xLen"].asInt()), (int16_t)(coordinateTable[i][j]["yLen"].asInt()));
                lv_obj_align(m_scheduleItem[m_scheduleIndex], LV_ALIGN_TOP_LEFT, (int16_t)(189 + coordinateTable[i][j]["x"].asInt()), (int16_t)(244 + coordinateTable[i][j]["y"].asInt()));
                
                lv_style_set_border_width(&m_scheduleItemStyles[m_scheduleIndex], 3);
                lv_style_set_bg_color(&m_scheduleItemStyles[m_scheduleIndex], lv_color_make(0xA9, 0x88, 0xFF));
                lv_style_set_bg_opa(&m_scheduleItemStyles[m_scheduleIndex], (lv_opa_t)(155 + (100 * i /  coordinateTable.size())));
                

                std::string summary = coordinateTable[i][j]["summary"].asString();
                time_t startTime = coordinateTable[i][j]["start"].asInt64();
                time_t endTime = coordinateTable[i][j]["end"].asInt64();;
          
                std::tm* startTm = std::gmtime(&startTime);
                int startHour = startTm->tm_hour;
                int startMinute = startTm->tm_min;
                std::tm* endTm = std::gmtime(&endTime);
                int endHour = endTm->tm_hour;
                int endMinute = endTm->tm_min;
                
                std::string startPostfix = startHour >= 12 ? "pm" : "am";
                std::string endPostfix = endHour >= 12 ? "pm" : "am";

                std::string scheduleTimeInfo = std::to_string(startHour % 12) + ":" + std::to_string(startMinute) + startPostfix + " - ";
                scheduleTimeInfo = scheduleTimeInfo + std::to_string(endHour % 12) + ":" + std::to_string(endMinute) + endPostfix;

                //在窗体中创建日程的基本信息文本窗体
                //这里可以通过布局和不设置文本框的长度而是设置文本框根据文本长度自动扩张大小的模式lv_label_set_long_mode
                if(coordinateTable[i][j]["yLen"].asInt() < 88){
                    //窗体的高度小于显示的阈值时，需要在一行中显示信息，应该采取弹性布局中的一行多列排布
                    lv_obj_set_flex_flow(m_scheduleItem[m_scheduleIndex], LV_FLEX_FLOW_ROW);
                    lv_obj_set_flex_align(m_scheduleItem[m_scheduleIndex],LV_FLEX_ALIGN_START ,LV_FLEX_ALIGN_START ,LV_FLEX_ALIGN_START );
                }else{
                    //窗体的高度大于等于显示的阈值时，需要在不同行中显示信息，应该采取弹性布局中的一列多行排布
                    lv_obj_set_flex_flow(m_scheduleItem[m_scheduleIndex], LV_FLEX_FLOW_COLUMN);
                    lv_obj_set_flex_align(m_scheduleItem[m_scheduleIndex],LV_FLEX_ALIGN_START ,LV_FLEX_ALIGN_START ,LV_FLEX_ALIGN_START );
                }
                m_scheduleLabelItem = lv_label_create(m_scheduleItem[m_scheduleIndex]);
                lv_label_set_long_mode(m_scheduleLabelItem, LV_LABEL_LONG_DOT);
                lv_label_set_text_fmt(m_scheduleLabelItem, summary.c_str());
                lv_obj_add_style(m_scheduleLabelItem, &m_scheduleSummaryStyle, LV_PART_MAIN);
                m_scheduleLabelItem = lv_label_create(m_scheduleItem[m_scheduleIndex]);
                lv_label_set_long_mode(m_scheduleLabelItem, LV_LABEL_LONG_DOT);
                lv_label_set_text_fmt(m_scheduleLabelItem, scheduleTimeInfo.c_str());
                lv_obj_add_style(m_scheduleLabelItem, &m_scheduleTimeStyle, LV_PART_MAIN);
                lv_obj_add_style(m_scheduleItem[m_scheduleIndex], &m_scheduleItemStyles[m_scheduleIndex], LV_PART_MAIN);
            }
        }
            
    }

    void DailySchedule::TimeHour(){
        
        
        lv_style_set_border_width(&m_TimeHourItemStyle, 0);
        lv_style_set_radius(&m_TimeHourItemStyle, 0);
        
        lv_style_set_text_align(&m_TimeHourItemStyle, LV_TEXT_ALIGN_CENTER);
        lv_style_set_text_color(&m_TimeHourItemStyle, lv_color_make(0x33, 0x33, 0x33));
        lv_style_set_text_font(&m_TimeHourItemStyle, m_font20Normal.font);
        lv_style_set_text_opa(&m_TimeHourItemStyle, 153);

        int hours[5] = {(m_curtm ->tm_hour + 22) % 24 , (m_curtm ->tm_hour + 23) % 24, m_curtm ->tm_hour, (m_curtm ->tm_hour + 1) % 24, (m_curtm ->tm_hour + 2) % 24}; 
        int hourDesc;
        std::string hourfix;
        for(int i = 0; i < m_dotlineNum; i++){
            m_TimeHourItem = lv_label_create(m_dailyTransactionBottomLeftSupper);
            lv_obj_set_size(m_TimeHourItem, 65, 24);
            lv_obj_align(m_TimeHourItem, LV_ALIGN_TOP_RIGHT, 0 , (int16_t)(20 + m_padding + i * 6 * 34));
            if(m_dotlineNum == 5){
                hourDesc = hours[i];
            }else{
                hourDesc = hours[i + 1];
            }

            if(hourDesc >= 12){
                hourfix = "PM";
            }else{
                hourfix = "AM";
            }
            hourDesc = hourDesc % 12;
            hourfix = std::to_string(hourDesc) + " " + hourfix;
            lv_label_set_text_fmt(m_TimeHourItem, hourfix.c_str());
            lv_obj_add_style(m_TimeHourItem, &m_TimeHourItemStyle, LV_PART_MAIN);
        }
    }

    
    void DailySchedule::Dottedline(){
        //样式
        lv_style_set_radius(&m_DotlineFrameStyle, 0);
        lv_style_set_border_width(&m_DotlineFrameStyle, 0);
        
        lv_style_set_border_color(&m_DotlineItemStyle,  lv_palette_main(LV_PALETTE_GREY));
        // 设置边框的位置为上边
        lv_style_set_border_side(&m_DotlineItemStyle, LV_BORDER_SIDE_TOP);
        lv_style_set_border_width(&m_DotlineItemStyle, 2);
        lv_style_set_radius(&m_DotlineItemStyle, 0);
        lv_coord_t width;
        lv_obj_t * parentObj;
        for(int i = 0; i < 2; i++){
            if(i == 0){
                parentObj = m_dailyTransactionMiddleLeftSupper;
                width = 39;
               
            }else{
                parentObj = m_dailyTransactionBottomRightSupper;
                width = 1737;
            }
           
            for(int j = 0; j < m_dotlineNum; j++){
                m_DotlineItem = lv_obj_create(parentObj);
                lv_obj_set_size(m_DotlineItem, width, 1);
                lv_obj_align(m_DotlineItem, LV_ALIGN_TOP_RIGHT, 0 , (int16_t)(30 + m_padding + j * 6 * 34));
                lv_obj_add_style(m_DotlineItem, &m_DotlineItemStyle, LV_PART_MAIN);
            }
        }
    }

    bool DailySchedule::createFont(std::string path, uint16_t weight, uint16_t style, lv_ft_info_t &font){
        /*Create a font*/
        /*FreeType uses C standard file system, so no driver letter is required.*/
        font.name = path.c_str();
        font.weight = weight; 
        font.style = style;
        font.mem = NULL;
        if(!lv_ft_font_init(&font)) {
            LV_LOG_ERROR("create failed.");
            return false;
        }
        return true;
    }

    
}
